<?php


namespace app\common\service;

/**
 * Redis单例类
 * @package app\common\service
 *
 * @Author: Li Guo Xin <guoxinlee129@gmail.com>
 * @Date: 2020/4/28
 * @Time: 15:56
 */
class Redis
{
    private static $redis;
    private const USER_ACCESS_TOKEN_EXPIRY_SECONDS  = 3600;#登陆的token在redis中key过期的秒数
    private const USER_CREDENTIAL_RESET_PWD_SECONDS = 3600;#
    private const TABLE_DATA_SECONDS                = 3600;

    /**
     * Redis constructor.
     * @throws \Exception
     */
    private function __construct()
    {
        try {
            self::$redis = new \Redis();
            self::$redis->connect(env('redis.host'), env('redis.port'), env('redis.timeout'));
            self::$redis->auth(env('redis.password'));
            //self::$redis->multi(\Redis::PIPELINE);
            //var_dump(self::$redis->info('redis_version'));die;
            //foreach (self::$redis->info() as $item) {
            //    var_dump($item);
            //}
            //die;
            //self::$redis->setOption(\Redis::OPT_SERIALIZER, \Redis::SERIALIZER_IGBINARY);
            //$a = Db::connect();
            //var_dump($a->table('user1')
            //    ->find());
        } catch (\Exception $e) {
            throw $e;
        }
    }

    /**
     * @return \Redis
     * @throws \Exception
     *
     * @Author: Li Guo Xin <guoxinlee129@gmail.com>
     * @Date: 2020/6/3
     * @Time: 10:53
     */
    public static function getRedis(): \Redis
    {
        if (self::$redis === null) {
            new self();
        }
        return self::$redis;
    }

    /**
     * 通过token获取用户ID
     * @param $access_token
     * @param $type
     * @return bool|mixed|string
     * @throws \Exception
     */
    public static function getUserIdByAccessToken($access_token, $type = 'default')
    {
        switch ($type) {
            case 'admin':
                $accessKey = 'admin:access_token:';
                break;
            default:
                $accessKey = 'user:access_token:';
        }

        return self::getRedis()->get($accessKey.$access_token);
    }

    /**
     * 通过token获取用户ID
     * @param $access_token
     * @param $userid
     * @throws \Exception
     */
    public static function setAccessToken($access_token, $userid, $type = 'default'): void
    {
        switch ($type) {
            case 'admin':
                $accessKey  = 'admin:access_token:';
                $historyKey = 'admin_'.$userid.':access_token_history';
                break;
            default:
                $accessKey  = 'user:access_token:';
                $historyKey = 'user_'.$userid.':access_token_history';
        }
        //检查是否有旧的token
        $oldAccessToken = self::getRedis()->get($historyKey);
        if ($oldAccessToken) {
            //有旧的，删除
            self::getRedis()->del($accessKey.$oldAccessToken);
        }
        //设置token并记录
        self::getRedis()->set($historyKey, $access_token);
        self::getRedis()->set($accessKey.$access_token, $userid,
            self::USER_ACCESS_TOKEN_EXPIRY_SECONDS);
    }

    /**
     * 重置token的过期时间
     * @param $access_token
     * @param $type
     * @return bool
     * @throws \Exception
     */
    public static function addExpireForAccessToken($access_token, $type = 'default')
    {
        switch ($type) {
            case 'admin':
                return self::getRedis()->expire('user:admin_access_token:'.$access_token,
                    self::USER_ACCESS_TOKEN_EXPIRY_SECONDS);
            default:
                return self::getRedis()->expire('user:access_token:'.$access_token,
                    self::USER_ACCESS_TOKEN_EXPIRY_SECONDS);
        }

    }

    /**
     * 设置用户重置密码凭证
     * @param $user_id
     * @throws \Exception
     *
     * @Author: Li Guo Xin <guoxinlee129@gmail.com>
     * @Date: 2020/7/27
     * @Time: 17:19
     */
    public static function setUserResetPasswordCredentials($user_id): void
    {
        self::getRedis()->set('user_credential_reset_pwd:'.$user_id, true, self::USER_CREDENTIAL_RESET_PWD_SECONDS);
    }

    /**
     * 检查用户重置密码凭证
     * @param $user_id
     * @return bool
     * @throws \Exception
     *
     * @Author: Li Guo Xin <guoxinlee129@gmail.com>
     * @Date: 2020/7/27
     * @Time: 17:19
     */
    public static function checkUserResetPasswordCredentials($user_id): bool
    {
        return self::getRedis()->get('user_credential_reset_pwd:'.$user_id) === true;
    }

    /**
     * 获取数据表缓存
     * @param $type
     * @param  string  $biaoshi
     * @return array|bool|mixed|string
     * @throws \Exception
     *
     * @Author: Li Guo Xin <guoxinlee129@gmail.com>
     * @Date: 2020/7/27
     * @Time: 17:19
     */
    public static function tableGet($type, $biaoshi = '')
    {
        $key = 'table_'.$type;

        switch ($type) {
            case 'users':
                return self::getRedis()->hGetAll($key.':'.$biaoshi);
                break;
            default:
                return json_decode(self::getRedis()->get($key), true) ?? [];
                break;
        }
    }

    /**
     * 设置数据表缓存
     * @param $type
     * @param $data
     * @throws \Exception
     *
     * @Author: Li Guo Xin <guoxinlee129@gmail.com>
     * @Date: 2020/7/27
     * @Time: 17:59
     */
    public static function tableSet($type, $data): void
    {
        $key = 'table_'.$type;
        switch ($type) {
            case 'users':
                foreach ($data as $userInfo) {
                    self::getRedis()->hMSet($key.':'.$userInfo['id'], $userInfo);
                    self::getRedis()->expire($key.':'.$userInfo['id'], self::TABLE_DATA_SECONDS);
                }
                break;
            default:
                self::getRedis()->del($key);
                self::getRedis()->set($key, json_encode($data), self::TABLE_DATA_SECONDS);
                break;
        }
    }
}
